import time
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from IPython.core import payload
from rest_framework.permissions import AllowAny
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.core.exceptions import ObjectDoesNotExist
import json
import jwt
from django.conf import settings
from django.utils.text import slugify
from .models import *
from accounts.models import Teacher, Student
from django.core.paginator import Paginator
SECRET_KEY = settings.SECRET_KEY
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.core.files.storage import default_storage
from django.contrib.auth.decorators import login_required
from django.core.files.base import ContentFile
def decode_jwt_token(token):
    """解析JWT Token"""
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        return payload
    except:
        return None


@csrf_exempt
@require_http_methods(["POST"])
def create_course(request):
    """创建新课程（仅教师有权限）"""
    # 解析JWT Token
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Bearer '):
        return JsonResponse({'error': '未提供认证令牌'}, status=401)

    token = auth_header.split(' ')[1]
    payload = decode_jwt_token(token)
    print(f"payload: {payload}")

    if not payload:
        return JsonResponse({'error': '无效的认证令牌'}, status=401)

    # 验证用户类型为教师
    user_type = payload.get('user_type')
    if user_type != 'teacher':
        return JsonResponse({'error': '权限不足，仅教师可创建课程'}, status=403)

    teacher_id = payload.get('user_id')
    if not teacher_id:
        return JsonResponse({'error': 'Token中缺少教师ID'}, status=401)

    try:
        # 获取教师对象
        teacher = Teacher.objects.get(id=teacher_id)
    except ObjectDoesNotExist:
        return JsonResponse({'error': '教师用户不存在'}, status=404)

    # 解析请求数据
    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'error': '无效的JSON格式'}, status=400)

    # 验证必填字段
    required_fields = ['title', 'description', 'status']
    for field in required_fields:
        if field not in data:
            return JsonResponse({'error': f'缺少必填字段: {field}'}, status=400)

    # 生成slug（课程标识）
    data['slug'] = slugify(data['title'])

    # 检查slug唯一性
    if Course.objects.filter(slug=data['slug']).exists():
        return JsonResponse({'error': '课程标识已存在，请修改课程标题'}, status=400)

    # 设置默认值
    data.setdefault('duration', 1)
    data.setdefault('learning_objectives', '')
    data.setdefault('requirements', '')

    # 创建课程
    course = Course.objects.create(
        teacher=teacher,
        title=data['title'],
        slug=data['slug'],
        description=data['description'],
        learning_objectives=data.get('learning_objectives', ''),
        requirements=data.get('requirements', ''),
        duration=data.get('duration', 1),
        status=data['status'],
        published_at=time.strftime('%Y-%m-%d %H:%M:%S') if data['status'] == 'published' else None
    )

    return JsonResponse({
        'status': 'success',
        'message': '课程创建成功',
        'data': {
            'course_id': course.id,
            'slug': course.slug,
            'title': course.title,
            'teacher': course.teacher.name,
            'status': course.status,
            'created_at': course.created_at.strftime('%Y-%m-%d %H:%M:%S')
        }
    }, status=201)


@csrf_exempt
@require_http_methods(["GET"])
def get_course_detail(request, slug):
    """获取课程详情"""
    try:
        # 获取课程对象
        course = Course.objects.get(slug=slug)

        # 构建课程详情数据
        course_data = {
            'id': course.id,
            'slug': course.slug,
            'title': course.title,
            'teacher': {
                'id': course.teacher.teacher_id,
                'name': course.teacher.name
            },
            'description': course.description,
            'learning_objectives': course.learning_objectives,
            'requirements': course.requirements,
            'duration': course.duration,
            'status': course.status,
            'published_at': course.published_at.strftime('%Y-%m-%d %H:%M:%S') if course.published_at else None,
            'created_at': course.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'enrollment_count': course.get_enrollment_count(),
            'is_enrolled': False  # 默认为未选课
        }

        # 检查当前用户是否已选课（如果已登录）
        auth_header = request.headers.get('Authorization', '')
        if auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
            payload = decode_jwt_token(token)

            if payload and payload.get('user_type') == 'student':
                student_id = payload.get('user_id')
                try:
                    student = Student.objects.get(student_id=student_id)
                    # 检查是否存在选课记录
                    course_data['is_enrolled'] = Enrollment.objects.filter(
                        student=student, course=course
                    ).exists()
                except:
                    pass

        return JsonResponse({
            'status': 'success',
            'message': '获取课程详情成功',
            'data': course_data
        }, status=200)

    except Course.DoesNotExist:
        return JsonResponse({'error': '课程不存在'}, status=404)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@csrf_exempt
@require_http_methods(["POST"])
def enroll_course(request):
    """学生通过课程标识加入课程"""
    data = json.loads(request.body.decode('utf-8'))
    student_id = data['user_id']
    slug = data['slug']
    print(f"data: {data}")
    if not student_id:
        return JsonResponse({'error': 'Token中缺少学生ID'}, status=401)
    try:
        # 获取学生和课程对象
        student = Student.objects.get(id=student_id)
        course = Course.objects.get(slug=slug)

        # 检查课程状态是否允许选课
        # if course.status != 'published':
        #     return JsonResponse({'error': '该课程尚未发布，无法选课'}, status=400)

        # 检查是否已选课（通过unique_together约束自动防止重复选课）
        try:
            Enrollment.objects.create(
                student=student,
                course=course
            )
            return JsonResponse({
                'status': 'success',
                'message': '选课成功',
                'data': {
                    'course_title': course.title,
                    'enrolled_at': time.strftime('%Y-%m-%d %H:%M:%S')
                }
            }, status=201)
        except Exception as e:
            if 'Duplicate' in str(e):
                return JsonResponse({'error': '你已加入该课程'}, status=400)
            raise e

    except Student.DoesNotExist:
        return JsonResponse({'error': '学生用户不存在'}, status=404)
    except Course.DoesNotExist:
        return JsonResponse({'error': '课程不存在'}, status=404)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@csrf_exempt
@require_http_methods(["GET"])
# @api_view(['GET'])
# @permission_classes([IsAuthenticated])
def get_course_students(request, slug):
    """获取选修某门课程的所有学生列表（带分页）"""
    try:
        # 验证请求用户权限（仅教师或管理员可查看）
        auth_header = request.headers.get('Authorization', '')
        if not auth_header.startswith('Bearer '):
            return JsonResponse({'error': '未提供认证令牌'}, status=401)

        token = auth_header.split(' ')[1]
        payload = decode_jwt_token(token)
        print(f"payload: {payload}")

        if not payload:
            return JsonResponse({'error': '无效的认证令牌'}, status=401)

        # 获取课程对象
        try:
            course = Course.objects.get(slug=slug)
        except Course.DoesNotExist:
            return JsonResponse({'error': '课程不存在'}, status=404)

        # 获取该课程的所有选课记录并关联学生信息
        enrollments = Enrollment.objects.filter(course=course).select_related('student')

        # 排序（默认按选课时间倒序）
        sort_by = request.GET.get('sort_by', '-enrolled_at')
        if sort_by in ['enrolled_at', '-enrolled_at', 'progress', '-progress']:
            enrollments = enrollments.order_by(sort_by)

        # 分页
        page_number = request.GET.get('page', 1)
        page_size = request.GET.get('page_size', 20)
        paginator = Paginator(enrollments, page_size)

        try:
            current_page = paginator.page(page_number)
        except:
            return JsonResponse({'error': '无效的页码'}, status=400)

        # 构建学生简略信息列表
        students_data = []
        for enrollment in current_page:
            student = enrollment.student
            students_data.append({
                'student_id': student.student_id,
                'name': student.name,
                'avatar': student.avatar.url if hasattr(student, 'avatar') else None,
                'enrolled_at': enrollment.enrolled_at.strftime('%Y-%m-%d %H:%M:%S'),
                'progress': enrollment.progress,
                'is_completed': enrollment.is_completed
            })

        return JsonResponse({
            'status': 'success',
            'message': f'获取课程"{course.title}"的学生列表成功',
            'total': paginator.count,
            'page': int(page_number),
            'page_size': int(page_size),
            'pages': paginator.num_pages,
            'data': students_data
        }, status=200)

    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


# courses/views.py

@require_http_methods(["PUT"])
@csrf_exempt
def update_course(request, slug):
    """更新课程信息的函数视图"""
    # 获取课程对象，不存在则返回404
    course = get_object_or_404(Course, slug=slug)

    # 权限验证：只有讲师或管理员可更新
    if course.teacher.user != request.user and not request.user.is_staff:
        return JsonResponse({
            'error': '权限不足，只有课程讲师或管理员可以更新'
        }, status=403)

    try:
        # 解析请求数据
        data = json.loads(request.body)

        # 序列化器验证数据
        serializer = CourseUpdateSerializer(course, data=data, partial=True)
        if not serializer.is_valid():
            return JsonResponse({
                'error': serializer.errors
            }, status=400)

        # 特殊处理：发布状态自动设置发布时间
        if 'status' in data and data['status'] == 'published':
            serializer.validated_data['published_at'] = serializer.validated_data.get(
                'published_at', timezone.now()
            )

        # 保存更新
        serializer.save()

        # 返回成功响应
        return JsonResponse({
            'status': 'success',
            'message': '课程信息更新成功',
            'data': {
                'id': course.id,
                'title': course.title,
                'slug': course.slug,
                'description': course.description,
                'status': course.status,
                'published_at': course.published_at.isoformat() if course.published_at else None,
                'updated_at': course.updated_at.isoformat()
            }
        }, status=200)

    except json.JSONDecodeError:
        return JsonResponse({
            'error': '请求数据格式错误，请提供JSON格式数据'
        }, status=400)
    except Exception as e:
        return JsonResponse({
            'error': str(e)
        }, status=500)


@csrf_exempt
@require_http_methods(["POST"])
def upload_course_material(request, slug):
    """上传课程学习资料（PDF、Word等电子书籍文件）"""
    # 解析JWT Token
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Bearer '):
        return JsonResponse({'error': '未提供认证令牌'}, status=401)

    token = auth_header.split(' ')[1]
    payload = decode_jwt_token(token)
    print(f"payload: {payload}")

    if not payload:
        return JsonResponse({'error': '无效的认证令牌'}, status=401)

    # 验证用户类型为教师
    user_type = payload.get('user_type')
    if user_type != 'teacher':
        return JsonResponse({'error': '权限不足，仅教师可上传课程资料'}, status=403)

    teacher_id = payload.get('user_id')
    if not teacher_id:
        return JsonResponse({'error': 'Token中缺少教师ID'}, status=401)

    try:
        # 获取教师对象
        teacher = Teacher.objects.get(id=teacher_id)
    except ObjectDoesNotExist:
        return JsonResponse({'error': '教师用户不存在'}, status=404)

    # 获取课程对象
    try:
        course = Course.objects.get(slug=slug)
    except Course.DoesNotExist:
        return JsonResponse({'error': '课程不存在'}, status=404)

    # 验证教师是否为课程创建者
    if course.teacher.id != teacher_id:
        return JsonResponse({'error': '权限不足，你不是该课程的创建者'}, status=403)

    # 检查是否有文件上传
    if 'file' not in request.FILES:
        return JsonResponse({'error': '未上传文件'}, status=400)

    file = request.FILES['file']

    # 检查文件大小限制（示例：100MB）
    max_size = 100 * 1024 * 1024  # 100MB
    if file.size > max_size:
        return JsonResponse({'error': f'文件大小超过限制（最大 {max_size / (1024 * 1024)}MB）'}, status=400)

    # 获取文件名和扩展名
    filename = file.name
    name, extension = os.path.splitext(filename)
    valid_extensions = ['.pdf', '.doc', '.docx', '.ppt', '.pptx', '.txt', '.xlsx', '.xls']

    # 检查文件类型
    if extension.lower() not in valid_extensions:
        allowed_types = ', '.join(valid_extensions)
        return JsonResponse({'error': f'不支持的文件类型。允许的类型：{allowed_types}'}, status=400)

    # 生成唯一文件名，避免冲突
    timestamp = timezone.now().strftime("%Y%m%d%H%M%S")
    unique_filename = f"{slug}_{timestamp}{extension}"

    # 保存文件
    file_path = default_storage.save(f'course_materials/{unique_filename}', ContentFile(file.read()))

    # 创建课程资料记录
    material = CourseMaterial.objects.create(
        course=course,
        title=request.POST.get('title', filename),
        file=file_path,
        file_type=extension.lower().replace('.', ''),
        uploader=teacher
    )

    return JsonResponse({
        'status': 'success',
        'message': '文件上传成功',
        'data': {
            'id': material.id,
            'title': material.title,
            'file_type': material.file_type,
            'uploaded_at': material.uploaded_at.strftime('%Y-%m-%d %H:%M:%S'),
            'file_url': material.file.url,
            'course': course.title
        }
    }, status=201)


@csrf_exempt
@require_http_methods(["POST"])
def upload_course_materials(request, slug):
    """上传多个课程资料文件（支持PDF、Word等格式）"""
    # 解析JWT Token
    auth_header = request.headers.get('Authorization', '')
    if not auth_header.startswith('Bearer '):
        return JsonResponse({'error': '未提供认证令牌'}, status=401)

    token = auth_header.split(' ')[1]
    payload = decode_jwt_token(token)
    if not payload:
        return JsonResponse({'error': '无效的认证令牌'}, status=401)

    # 验证用户类型为教师
    if payload.get('user_type') != 'teacher':
        return JsonResponse({'error': '权限不足，仅教师可上传资料'}, status=403)

    # 获取课程对象并验证权限
    try:
        course = Course.objects.get(slug=slug)
        if payload.get('user_id') != course.teacher.id:
            return JsonResponse({'error': '只有课程创建者可以上传资料'}, status=403)
    except Course.DoesNotExist:
        return JsonResponse({'error': '课程不存在'}, status=404)

    # 检查是否有文件上传
    if 'files' not in request.FILES:
        return JsonResponse({'error': '未上传文件'}, status=400)

    uploaded_files = request.FILES.getlist('files')  # 获取所有上传的文件
    if not uploaded_files:
        return JsonResponse({'error': '未上传文件'}, status=400)

    # 配置文件类型和大小限制
    allowed_types = [
        'application/pdf', 'application/msword',
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation'
    ]
    max_file_size = 100 * 1024 * 1024  # 100MB

    created_materials = []
    errors = []

    # 循环处理每个文件
    for file in uploaded_files:
        # 检查文件类型
        if file.content_type not in allowed_types:
            errors.append(f"文件 {file.name} 类型不支持，允许格式：PDF, Word, PPT")
            continue

        # 检查文件大小
        if file.size > max_file_size:
            errors.append(f"文件 {file.name} 大小超过限制（最大100MB）")
            continue

        try:
            # 生成唯一文件名
            timestamp = timezone.now().strftime('%Y%m%d%H%M%S')
            original_name = file.name
            file_extension = os.path.splitext(original_name)[1]
            unique_filename = f"{timestamp}_{slugify(os.path.splitext(original_name)[0])}{file_extension}"

            # 确定文件存储路径
            course_dir = slugify(course.title)
            file_dir = os.path.join('course_materials', course_dir)
            if not os.path.exists(file_dir):
                os.makedirs(file_dir, exist_ok=True)

            file_path = os.path.join(file_dir, unique_filename)

            # 保存文件到服务器
            with open(os.path.join(settings.MEDIA_ROOT, file_path), 'wb+') as destination:
                for chunk in file.chunks():
                    destination.write(chunk)

            # 提取文件标题（优先使用请求中的title，若无则使用文件名）
            title = request.POST.get('title') or os.path.splitext(original_name)[0]

            # 创建数据库记录
            material = CourseMaterial.objects.create(
                course=course,
                title=title,
                file=file_path,
                file_type=file.content_type,
                file_size=file.size,
                uploaded_by=Teacher.objects.get(id=payload.get('user_id'))
            )

            created_materials.append({
                'id': material.id,
                'title': material.title,
                'file_url': request.build_absolute_uri(f'/media/{file_path}'),
                'file_type': material.file_type,
                'file_size': material.file_size,
                'uploaded_at': material.uploaded_at.strftime('%Y-%m-%d %H:%M:%S')
            })

        except Exception as e:
            errors.append(f"文件 {file.name} 上传失败：{str(e)}")

    # 构建响应结果
    result = {
        'status': 'success' if not errors else 'partial',
        'message': f'成功上传 {len(created_materials)} 个文件，{len(errors)} 个文件上传失败',
        'data': {
            'uploaded': created_materials,
            'errors': errors
        }
    }

    status_code = 207 if errors else 201  # 207 Multi-Status 表示部分成功
    return JsonResponse(result, status=status_code)

